package com.hzy.fivepalace.wx.service;

import com.alibaba.fastjson2.JSON;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.hzy.fivepalace.common.consts.CommConsts;
import com.hzy.fivepalace.common.consts.RedisKeyConsts;
import com.hzy.fivepalace.common.exception.AppException;
import com.hzy.fivepalace.common.service.redis.RedisCache;
import com.hzy.fivepalace.common.type.CollectTypeEnums;
import com.hzy.fivepalace.common.type.OrderStatusEnums;
import com.hzy.fivepalace.common.type.VipTypeEnums;
import com.hzy.fivepalace.common.util.DateUtils;
import com.hzy.fivepalace.common.util.IpUtils;
import com.hzy.fivepalace.common.util.OrderUtils;
import com.hzy.fivepalace.common.util.ResponseUtil;
import com.hzy.fivepalace.db.dao.DtsOrderGoodsMapper;
import com.hzy.fivepalace.db.dao.DtsOrderMapper;
import com.hzy.fivepalace.db.dao.DtsVipConfigMapper;
import com.hzy.fivepalace.db.dao.ex.CommentMapperEx;
import com.hzy.fivepalace.db.dao.ex.DtsVipConfigMapperEx;
import com.hzy.fivepalace.db.domain.*;
import com.hzy.fivepalace.db.service.*;
import com.hzy.fivepalace.db.vo.wx.WxVipConfigDto;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

@Service
public class WxVipService {

    @Resource
    private DtsVipConfigMapperEx dtsVipConfigMapperEx;

    @Resource
    private DtsVipConfigMapper dtsVipConfigMapper;

    @Autowired
    private DtsGoodsSecurityService goodsSecurityService;

    @Autowired
    private DtsLogisticsService logisticsService;

    @Resource
    private CommentMapperEx commentMapperEx;

    @Autowired
    private DtsVipConfigService dtsVipConfigService;

    @Resource
    private RedisCache redisCache;

    @Autowired
    private DtsGoodsService goodsService;

    @Resource
    private DtsOrderGoodsMapper dtsOrderGoodsMapper;

    /**
     * 微信小程序支付回调地址
     */
    @Value("${hzy.wx.notify-url}")
    private String wxPayCallbackUrl;


    @Autowired
    private WxPayService wxPayService;



    @Resource
    private DtsOrderMapper dtsOrderMapper;


    @Autowired
    private DtsUserService userService;

    @Resource
    private Redisson redisson;

    /**
     * 购买会员
     * @param userId
     * @param vipId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public Object byVip(Integer userId,Long vipId){
        if(null==vipId|| vipId.intValue()<1){
            return ResponseUtil.fail("参数【vipId】为空");
        }
        RLock lock = redisson.getLock("wx_byVip_" + userId);
        if (lock.isLocked()) {
            return ResponseUtil.frequent();
        }
        lock.lock(30, TimeUnit.SECONDS);

        DtsUser user = userService.findById(userId);
        if (null == user) {
            lock.unlock();
            return ResponseUtil.unlogin();
        }
        DtsVipConfig vipConfig=dtsVipConfigMapper.selectByPrimaryKey(vipId);
        if(null==vipConfig||vipConfig.getDeleted()){
            lock.unlock();
            return ResponseUtil.fail("会员商品不存在");
        }
        if(null==vipConfig.getByPrice()||vipConfig.getByPrice().compareTo(new BigDecimal("0"))<=0){
            lock.unlock();
            return ResponseUtil.fail("平台价格配置错误");
        }
        VipTypeEnums vipTypeEnums=VipTypeEnums.getEnum(vipConfig.getVipType());
        if(user.getVipType().equals(vipConfig.getVipType())){
            lock.unlock();
            return ResponseUtil.fail("购买失败,您已是"+vipTypeEnums.getDesc());
        }
        if(vipConfig.getVipType().intValue()<user.getVipType().intValue()){
            lock.unlock();
            return ResponseUtil.fail("无法购买比当前小的会员");
        }

        //响应结果
        Map<String, Object> responseResult = new HashMap<>();
        //初始化返回信息
        //微信支付数据
        responseResult.put("wxPayInfo", null);
        //订单编号
        responseResult.put("orderNo", null);
        //订单id
        responseResult.put("orderId", null);
        //订单结束时间
        responseResult.put("orderEndTime", null);

        //当前系统时间
        Calendar calendar = Calendar.getInstance();
        LocalDateTime dateLocal = LocalDateTime.now();
        Date date = new Date();

        //生成订单编号
        String orderNo = OrderUtils.generateOrderNo();
        DtsOrderWithBLOBs order = new DtsOrderWithBLOBs();
        order.setUserId(userId);
        order.setOrderSn(orderNo);
        order.setOrderStatus((short) OrderStatusEnums.TYPE0.getType());
        order.setGoodsPrice(vipConfig.getByPrice());
        order.setFreightPrice(new BigDecimal("0.00"));
        order.setCouponPrice(new BigDecimal("0.00"));
        order.setOrderPrice(vipConfig.getByPrice());
        order.setActualPrice(new BigDecimal("0.00"));
        order.setEndTime(DateUtils.addMinutes(date, CommConsts.orderValidMinute).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        order.setAddTime(dateLocal);
        order.setUpdateTime(dateLocal);
        order.setDeleted(false);
        order.setComments((short) 0);
        order.setIsByVip(true);
        order.setVipType(vipTypeEnums.getId());
        order.setShareUserId(user.getShareUserId());
        //订单信息入库
        dtsOrderMapper.insertSelective(order);

        DtsGoods goods = goodsService.getVipGoodsById(vipConfig.getGoodsId());
        if (null != goods) {
            DtsOrderGoods orderGoods = new DtsOrderGoods();
            orderGoods.setGoodsId(goods.getId());
            orderGoods.setOrderId(order.getId());
            orderGoods.setGoodsName(goods.getName());
            orderGoods.setProductId(0);
            orderGoods.setNumber((short)1);
            orderGoods.setPrice(vipConfig.getByPrice());
            orderGoods.setSpecifications(new String[]{});
            orderGoods.setPicUrl(goods.getPicUrl());
            orderGoods.setAddTime(dateLocal);
            orderGoods.setUpdateTime(dateLocal);
            orderGoods.setDeleted(false);
            dtsOrderGoodsMapper.insertSelective(orderGoods);
        }

        try {
            WxPayMpOrderResult wxPayMpOrderResult = createWxAPPOrder("购买会员", orderNo, order.getOrderPrice(), user.getWeixinOpenid(), calendar);
            //去掉appid字段返回
            wxPayMpOrderResult.setAppId(null);
            //设置微信支付数据
            responseResult.put("wxPayInfo", wxPayMpOrderResult);
            //订单编号
            responseResult.put("orderNo", orderNo);
            //订单结束时间
            responseResult.put("orderEndTime", DateUtils.addMinutes(date, CommConsts.orderValidMinute).getTime());
            //插入一个缓存，用于订单过期监听
            redisCache.setCacheObject(RedisKeyConsts.ORDER_TIME_OUT_LISTENING_KEY + order.getOrderSn(), order.getOrderSn(), CommConsts.orderValidMinute, TimeUnit.MINUTES);
        } catch (Exception e) {
            lock.unlock();
            throw new AppException("微信支付服务异常");
        }

        //订单id
        responseResult.put("orderId", order.getId());
        lock.unlock();
        return ResponseUtil.ok(responseResult);
    }

    /**
     * 创建微信小程序支付订单
     *
     * @param goodsName  商品名称
     * @param orderNo    订单编号
     * @param price      价格
     * @param userOpenid 用户openid
     * @param calendar   时间
     * @return
     * @throws WxPayException
     */
    public WxPayMpOrderResult createWxAPPOrder(String goodsName,
                                               String orderNo, BigDecimal price, String userOpenid,
                                               Calendar calendar) throws WxPayException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //拼接微信小程序支付参数
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
        //支付回调地址
        wxPayUnifiedOrderRequest.setNotifyUrl(wxPayCallbackUrl);
        //商品名称
        wxPayUnifiedOrderRequest.setBody(goodsName);
        //订单编号
        wxPayUnifiedOrderRequest.setOutTradeNo(orderNo);
        //订单金额
        wxPayUnifiedOrderRequest.setTotalFee(price.multiply(new BigDecimal(100)).intValue());
        //交易类型为JSAPI支付
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        wxPayUnifiedOrderRequest.setSpbillCreateIp(null == request ? "127.0.0.1" : IpUtils.getIpAddr(request));
        //用户在当前小程序中的唯一标识
        wxPayUnifiedOrderRequest.setOpenid(userOpenid);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        //交易起始时间
        wxPayUnifiedOrderRequest.setTimeStart(formatter.format(calendar.getTime()));
        //交易结束时间 (当前15分钟后的时间-1分钟也就是9分钟，避免在到期前几秒支付成功后，redis监听过期订单时该订单被删除，系统订单有效是15分钟，传给微信的是15-1为14分钟)
        wxPayUnifiedOrderRequest.setTimeExpire(DateUtils.getMinuteAfter(calendar, CommConsts.orderValidMinute - 1));
        return wxPayService.createOrder(wxPayUnifiedOrderRequest);
    }

    /**
     * 获取vip配置详情
     * @param userId
     * @param vipId
     * @return
     */
    public Object getVipConfigDetail(Integer userId, Long vipId) {
        DtsUser user =null!=userId?userService.findById(userId):null;

        DtsVipConfig vipInfo=dtsVipConfigMapper.selectByPrimaryKey(vipId);
        if(null==vipInfo||vipInfo.getDeleted()){
            return ResponseUtil.fail("会员商品不存在");
        }

        DtsGoods info = goodsService.getVipGoodsById(vipInfo.getGoodsId());
        if (null == info) {
            return ResponseUtil.badArgument("会员商品未配置详情");
        }

        Map<String, Object> data = new HashMap<>();
        data.put("productList", new ArrayList<>());//货品集合
        info.setCounterPrice( vipInfo.getByPrice());
        info.setSales(vipInfo.getSales().intValue());
        info.setRetailPrice( vipInfo.getByPrice());
        info.setWholesalePrice(vipInfo.getByPrice());
        String price = vipInfo.getByPrice().stripTrailingZeros().toPlainString();;
        //获取物流说明
        data.put("logisticsInstructions", logisticsService.getLogisticsInstructions());
        data.put("noDeliveryRegionList", new ArrayList<>());
        Map<String, Object> infoJson = JSON.parseObject(JSON.toJSONString(info));
        infoJson.put("retailPrice", price);
        data.put("goodsInfo", infoJson);//商品详情
        //获取商品保障列表
        data.put("goodsSecurityList", goodsSecurityService.selectList());
        data.put("isCollectFresh", false);//是否收藏
        data.put("commentCount", commentMapperEx.getCommentListByGoodsIdCount(vipInfo.getGoodsId()));//商品评论总数
        BigDecimal commission=new BigDecimal("0");
        if(null!=user&&!user.getVipType().equals(0)){
            if (user.getVipType().intValue() == VipTypeEnums.TYPE1.getId()) {
                if (vipInfo.getVipType().intValue() == VipTypeEnums.TYPE1.getId()) {
                    commission=vipInfo.getOneLevelExtendAmount();
                }
            }else if (user.getVipType().intValue() == VipTypeEnums.TYPE2.getId()) {
                if (vipInfo.getVipType().intValue() == VipTypeEnums.TYPE1.getId()) {
                    commission=vipInfo.getOneLevelExtendAmount();
                }
            }else if (user.getVipType().intValue() == VipTypeEnums.TYPE3.getId()) {
                if (vipInfo.getVipType().intValue() == VipTypeEnums.TYPE1.getId() || vipInfo.getVipType().intValue() == VipTypeEnums.TYPE2.getId()) {
                    commission=vipInfo.getOneLevelExtendAmount();
                }
            }else if (user.getVipType().intValue() == VipTypeEnums.TYPE4.getId()) {
                commission=vipInfo.getOneLevelExtendAmount();
            }
        }
        if(commission.compareTo(new BigDecimal("0"))<0){
            commission=new BigDecimal("0");
        }
        data.put("commission", commission);

        return ResponseUtil.ok(data);
    }

    /**
     * 获取会员配置列表
     * @return
     */
    public Object getVipConfigList() {

        List<WxVipConfigDto> list=dtsVipConfigMapperEx.getWxVipConfigList();
        if(CollectionUtils.isEmpty(list)){
            list=new ArrayList<>();
        }
        return ResponseUtil.ok(list);
    }
}
